package com.lai.hospital.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.lai.hospital.dao.RoleDao;
import com.lai.hospital.dao.UserAuthDao;
import com.lai.hospital.dao.UserInfoDao;
import com.lai.hospital.dto.UserDetailDTO;
import com.lai.hospital.entity.Role;
import com.lai.hospital.entity.UserAuth;
import com.lai.hospital.entity.UserInfo;
import com.lai.hospital.enums.ZoneEnum;
import com.lai.hospital.exception.BizException;
import com.lai.hospital.utils.IpUtils;
import eu.bitwalker.useragentutils.UserAgent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
import java.util.Objects;


/**
 * @author : lai
 * @version V1.0
 * @Project: hospital-springboot
 * @Package com.lai.hospital.service.impl
 * @Description: 自定义认证数据源
 * @date Date : 2022年11月18日 12:46
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private HttpServletRequest request;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private UserAuthDao userAuthDao;

    @Autowired
    private UserInfoDao userInfoDao;

    /**
     * 认证流程
     * @param username  用户名
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isBlank(username)) {
            throw new BizException("用户名或手机号不能为空");
        }
        UserAuth userAuth = userAuthDao.selectOne(new LambdaQueryWrapper<UserAuth>()
                .select(UserAuth::getId, UserAuth::getUserInfoId, UserAuth::getUsername,  UserAuth::getPassword, UserAuth::getLoginType)
                .eq(UserAuth::getUsername, username)
                .or()
                .eq(UserAuth::getPhone,username));
        if(Objects.isNull(userAuth)){
            throw new BizException("用户名或手机号不存在");
        }
        return convertUserDetail(userAuth,request);
    }

    /**
     * 封装用户登录细节信息
     * @param userAuth
     * @param request
     * @return
     */
    public UserDetailDTO convertUserDetail(UserAuth userAuth, HttpServletRequest request){
        //查询账号基本信息
        UserInfo userInfo = userInfoDao.selectOne(new LambdaQueryWrapper<UserInfo>()
                .select(UserInfo::getNickname, UserInfo::getAvatar, UserInfo::getLocation, UserInfo::getIsDisable)
                .eq(UserInfo::getId, userAuth.getUserInfoId()));
        //查询账号角色列表
        List<String> roleList = roleDao.selectListRoleByUserInfoId(userAuth.getUserInfoId());
        //获取用户的设备信息
        String ipAddress = IpUtils.getIpAddress(request);
        String ipSource = IpUtils.getIpSource(ipAddress);
        UserAgent userAgent = IpUtils.getUserAgent(request);

        UserDetailDTO userDetailDTO = UserDetailDTO.builder()
                .id(userAuth.getId())
                .userInfoId(userAuth.getUserInfoId())
                .username(userAuth.getUsername())
                .password(userAuth.getPassword())
                .phone(userAuth.getPhone())
                .loginType(userAuth.getLoginType())
                .roleList(roleList)
                .nickname(userInfo.getNickname())
                .avatar(userInfo.getAvatar())
                .location(userInfo.getLocation())
                .isDisable(userInfo.getIsDisable())
                .ipAddress(ipAddress)
                .ipSource(ipSource)
                .os(userAgent.getOperatingSystem().getName())
                .browser(userAgent.getBrowser().getName())
                //最后登录时间    配置时区
                .lastLoginTime(LocalDateTime.now(ZoneId.of(ZoneEnum.SHANGHAI.getZone())))
                .build();
        return userDetailDTO;
    }
}
